[org 0x1000]

KERNEL_ADDR equ 0x18000

mov sp, 0x1000

read_kernel:
    sub esp, (4 * 3)

    mov dword [esp], KERNEL_ADDR
    mov dword [esp + 4], 0
    mov dword [esp + 8], 10; LBA

.read_blocks:
    mov eax, [esp]
    mov ebx, [esp + 4]
    mov ecx, [esp + 8]

    mov [dap.offset], ax
    shr eax, 4
    and eax, ~0xfff
    mov [dap.segment], ax
    mov [dap.lbal], cx

    call read_disk

    add dword [esp], (512 * 2)
    add dword [esp + 4], (512 * 2)
    add dword [esp + 8], 2

    cmp dword [esp + 4], KERNEL_SIZE
    jae .done

    jmp .read_blocks

.done:
    add esp, (4 * 3)

dectet_memory:
    mov edx, 0x534d4150
    xor ebx, ebx
    mov di, ards_buf
    mov dword [ards_count], 0

.next:
    mov eax, 0xe820
    mov ecx, 20

    int 0x15
    jc .error

    cmp eax, edx
    jnz .error

    add di, cx
    inc dword [ards_count]

    cmp ebx, 0
    jz .done

    jmp .next

.error:
    mov si, .message
    call print
    .message db "Detecting Memory Error!", 10, 13, 0

.done:

xchg bx, bx

cli

in al, 0x92
or al, 0b10
out 0x92, al

lgdt [gdt_ptr]

mov eax, cr0
or al, 1
mov cr0, eax

jmp dword code_selector: prepare_protection_mode

print:
    mov ah, 0xe
.next:
    mov al, [si]
    cmp al, 0
    jz .done
    int 0x10
    inc si
    jmp .next
.done:
    ret

read_disk:
    mov ah, 0x42
    mov dl, 0x80
    mov si, dap
    int 0x13

    ret

MAGIC equ 0x20250601

[bits 32]

prepare_protection_mode:
    mov ax, data_selector
    mov ds, ax
    mov es ,ax
    mov fs, ax
    mov es, ax
    mov ss, ax

    mov esp, 0x20000

    mov eax, MAGIC
    mov ecx, ards_count

    jmp dword code_selector: ENTRYPOINT

    align 4
dap:
    .size db 0x10
    .unused db 0x00
    .sectors dw 2

    .offset dw 0x0000
    .segment dw 0x1000
    .lbal dd 10
    .lbah dd 0

code_selector equ (1 << 3)
data_selector equ (2 << 3)

gdt_ptr:
    dw (gdt_end - gdt_base) - 1
    dd gdt_base

memory_base equ 0x0
memory_limit equ 0xfffff

gdt_base:
    dd 0, 0
gdt_code:
    dw memory_limit & 0xffff
    dw memory_base & 0xffff
    db (memory_base >> 16) & 0xff
    db 0b1_00_1_1010
    db ((memory_limit >> 16) & 0xff) | (0b1100_0000)
    db (memory_base >> 24) & 0xff
gdt_data:
    dw memory_limit & 0xffff
    dw memory_base & 0xffff
    db (memory_base >> 16) & 0xff
    db 0b1_00_1_0010
    db ((memory_limit >> 16) & 0xff) | (0b1100_0000)
    db (memory_base >> 24) & 0xff
gdt_end:

times 510 - ($ - $$) db 0
dw 0xaa55

ards_count dd 0
ards_buf: